const express = require('express');
const fs = require('fs').promises;
const mime = require('mime-types');
const CacheManager = require("./components/CacheManager");
const VaultConfig = require("./components/VaultConfig");
const FileScanner = require("./components/FileScanner");
const RouteMapper = require("./components/RouteMapper");
const MarkdownHandler = require("./handlers/MarkdownHandler");
const HTMLHandler = require("./handlers/HTMLHandler");
const VideoHandler = require("./handlers/VideoHandler");
const SeriesHandler = require("./handlers/SeriesHandler");
const StaticFileHandler = require("./handlers/StaticFileHandler");
const {encodeRoutePath} = require("./util/url");
const FolderWatcher = require("./components/FolderWatcher");
class FileServer {
    constructor(config) {
        this.app = express();
        this.serverConfig = {host: config.host, port: config.port};
        this.config = new VaultConfig(config.vaults);
        this.cacheManager = new CacheManager();
        this.fileScanner = new FileScanner(this.cacheManager);
        this.routeMapper = new RouteMapper();
        this.folderWatcher = new FolderWatcher(this);
        this.handlers = this.initializeHandlers();
        this.routes = new Map();
        // this.setupMiddleware();
        // this.initializeRoutes();
    }
    initializeHandlers() {
        return {
            markdown: new MarkdownHandler(this),
            html: new HTMLHandler(this),
            video: new VideoHandler(this),
            series: new SeriesHandler(this),
            static: new StaticFileHandler(this),
        };
    }
    async initializeRoutes() {
        console.log('Initializing routes from vaults...');

        for (const vault of this.config.vaults) {
            try {
                console.log(`Scanning vault: ${vault.name} at ${vault.path}`);

                const files = await this.fileScanner.scanVault(vault);
                const routes = this.routeMapper.mapFilesToRoutes(files, vault);

                routes.forEach((route, index) => {
                    try {
                        console.log(`${index}/${routes.length} registering route /${route.prefix}${route.route}#~:~hint=${route.description}`)
                        this.routes.set(route.route, route);
                        this.registerRoute(route);
                    } catch (error) {
                        console.error(`✗ Failed to register route ${route.route}:`, error.message);
                    }
                });

                console.log(`✓ Vault ${vault.name}: ${routes.length} routes registered`);
            } catch (error) {
                console.error(`✗ Failed to scan vault ${vault.name}:`, error.message);
            }
        }

        // 注册健康检查路由
        this.app.get('/health', (req, res) => {
            res.json({
                status: 'ok',
                vaults: this.config.vaults.length,
                routes: this.routes.size,
                timestamp: new Date().toISOString()
            });
        });

        // 注册路由列表查看接口
        this.app.get('/api/routes', (req, res) => {
            const routeList = Array.from(this.routes.entries()).map(([route, info]) => ({
                route,
                filePath: info.filePath,
                handler: info.handler,
                type: info.type
            }));

            res.json(routeList);
        });

        this.app.get('/latest',(req, res) => {
            const routeList = Array.from(this.routes.entries()).map(([route, info]) => (
                info
            ));
            routeList.sort(function (a,b) {
                if (b.mtime > a.mtime) {
                    return 1;
                } else {
                    return -1;
                }
            });
            const latestRoute = routeList[0];

            res.redirect(`/${latestRoute.vault}${latestRoute.route}#~:~hint=${latestRoute.description}`);
        });
    }
    registerRoute(routeInfo) {
        const handler = this.handlers[routeInfo.handler];

        if (!handler) {
            console.error(`No handler found for type: ${routeInfo.handler}`);
            return;
        }
        // 对路径进行URL编码，确保特殊字符正确处理
        const encodedRoute = encodeRoutePath(routeInfo.route);
        this.app.get(`/${routeInfo.prefix}${encodedRoute}`, async (req, res) => {
            try {
                await handler.handle(req, res, routeInfo.filePath);
            } catch (error) {
                console.error(`Error handling route ${routeInfo.route}:`, error);
                res.status(500).json({
                    error: 'Failed to process file',
                    route: routeInfo.route
                });
            }
        });
        // // 注册主要路由（编码版本）
        // const primaryRoute = this.normalizeRoutePath(routeInfo.route);
        // this.registerRouteHandler(primaryRoute, handler, routeInfo);
        //
        // // 注册备用路由（处理尾部斜杠变体）
        // this.registerAlternativeRoutes(routeInfo.route, handler, routeInfo);

        // this.app.get(routeInfo.route, async (req, res) => {
        //     try {
        //         await handler.handle(req, res, routeInfo.filePath);
        //     } catch (error) {
        //         console.error(`Error handling route ${routeInfo.route}:`, error);
        //         res.status(500).json({
        //             error: 'Failed to process file',
        //             route: routeInfo.route
        //         });
        //     }
        // });
        //
        // // 为视频文件添加HEAD请求支持（用于获取文件信息）
        // if (routeInfo.handler === 'video') {
        //     this.app.head(routeInfo.route, async (req, res) => {
        //         try {
        //             const stats = await fs.stat(routeInfo.filePath);
        //             res.setHeader('Content-Length', stats.size);
        //             res.setHeader('Content-Type', mime.lookup(routeInfo.filePath) || 'video/mp4');
        //             res.status(200).end();
        //         } catch (error) {
        //             res.status(404).end();
        //         }
        //     });
        // }
    }
    // 对路径进行智能编码
    // encodeRoutePath(route) {
    //     // 分割路径组件，对每个部分单独编码
    //     // 分割路径组件，对每个部分单独编码
    //     const parts = route.split('/').map(part => {
    //         if (!part) return ''; // 空部分（如开头的空字符串）
    //
    //         // 对每个部分进行完整的URL编码
    //         // 使用encodeURIComponent处理大部分字符，但需要保留斜杠"/"
    //         let encodedPart = encodeURIComponent(part);
    //
    //         // 由于encodeURIComponent不会编码某些在URL路径中安全的字符
    //         // 但为了确保一致性，我们可以选择性地编码更多字符
    //         // 这里额外处理括号、&符号等可能引起问题的字符
    //         encodedPart = encodedPart
    //             .replace(/\(/g, '%28')   // 编码左括号
    //             .replace(/\)/g, '%29')   // 编码右括号
    //             .replace(/&/g, '%26')    // 编码&符号
    //             .replace(/\*/g, '%2A')   // 编码*符号
    //             .replace(/'/g, '%27')    // 编码单引号
    //             .replace(/!/g, '%21')    // 编码!
    //             .replace(/#/g, '%23')    // 编码#
    //             .replace(/\?/g, '%3F');  // 编码?
    //
    //         return encodedPart;
    //     });
    //
    //     // const parts = route.split('/').map(part => {
    //     //     if (!part) return ''; // 空部分（如开头的空字符串）
    //     //     // 只对包含非ASCII字符的部分进行编码
    //     //     return /[^\x00-\x7F]/.test(part) ? encodeURIComponent(part) : part;
    //     // });
    //
    //     return parts.join('/');
    // }
    setupMiddleware() {
        // 内置中间件：解析JSON和URL编码的请求体[7](@ref)
        this.app.use(express.json());
        this.app.use(express.urlencoded({ extended: true }));

        // 静态文件中间件[10](@ref)
        this.app.use('/static', express.static('public'));

        // 自定义日志中间件
        this.app.use(this.loggingMiddleware());

        // 错误处理中间件[7](@ref)
        this.app.use(this.errorHandlingMiddleware());

        // 404处理中间件（放在最后）[7](@ref)
        this.app.use(this.notFoundMiddleware());
    }

    loggingMiddleware() {
        return (req, res, next) => {
            const start = Date.now();
            console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);

            res.on('finish', () => {
                const duration = Date.now() - start;
                console.log(`${req.method} ${req.url} - ${res.statusCode} - ${duration}ms`);
            });

            next();
        };
    }

    errorHandlingMiddleware() {
        return (err, req, res, next) => {
            console.error('Error:', err.stack);

            if (err.code === 'ENOENT') {
                return res.status(404).json({
                    error: 'File not found',
                    path: err.path
                });
            }

            res.status(500).json({
                error: 'Internal server error',
                message: process.env.NODE_ENV === 'development' ? err.message : 'Something went wrong'
            });
        };
    }

    notFoundMiddleware() {
        return (req, res) => {
            res.status(404).json({
                error: 'Route not found',
                path: req.url,
                method: req.method
            });
        };
    }

    // 新增：启动文件监控
    async startFileWatching() {
        console.log('👀 Starting file system monitoring...');

        for (const vault of this.config.vaults) {
            if (vault.watchEnabled) { // 默认启用监控
                await this.folderWatcher.watchVault(vault);
            }
        }
    }
    async start(port = this.serverConfig.port, host = this.serverConfig.host) {
        try {
            await this.initializeRoutes();
            await this.startFileWatching();

            this.server = this.app.listen(port, host, () => {
                console.log(`🚀 File server running at http://${host}:${port}`);
                console.log(`📁 Serving ${this.config.vaults.length} vault(s) with ${this.routes.size} total routes`);
                console.log(`💾 Cache enabled: ${this.config.vaults.some(v => v.cacheEnabled)}`);
                console.log('✅ Server is ready!');
            });

            // 优雅关闭处理
            process.on('SIGTERM', () => this.gracefulShutdown());
            process.on('SIGINT', () => this.gracefulShutdown());

        } catch (error) {
            console.error('Failed to start server:', error);
            process.exit(1);
        }
    }

    async gracefulShutdown() {
        console.log('\n🛑 Shutting down gracefully...');

        if (this.server) {
            this.server.close(() => {
                console.log('✅ Server closed');
                process.exit(0);
            });

            // 强制退出超时处理
            setTimeout(() => {
                console.log('⚠️ Forcing shutdown after timeout');
                process.exit(1);
            }, 10000);
        }
    }
}

module.exports = FileServer;